/*
 * Classe StatSix
 *                          - Obtem os dados da estatística 6 da base de dados (SQLite3 + ADO.NET) 
 * 							- Guarda esses dados numa Lista (C# Collections)
 * 							- Ordena os dados
 * 							- Escreve os resultados na consola e no ficheiro de texto respectivo
 *							- Tem como atributo o estabelecimento para o qual será calculada a estatística
 *
 *@Author: Fábio Miguel Vitória Carreto - 5618 - Engenharia Informática - Diurno
 *@Version: 03/07/2011
 * 
 * 
 * */


using System;
using System.Collections.Generic;
using System.Data;
using Mono.Data.SqliteClient;
using System.IO;

public class StatSix
{
	public string estabelecimento;
	
	public StatSix (string estabelecimento)
	{
		this.estabelecimento = estabelecimento;
		
		List<StructFinal> statSix = this.getData();
		List<StructFinal> statOrdenada = this.mostraListaOrdenada(statSix);
		this.showResultsConsole(statOrdenada);
		this.showResultsFile(statOrdenada);
	}
	
	//Ordena os dados por ordem crescente da contagem na lista
	public List<StructFinal> mostraListaOrdenada(List<StructFinal> stat)
	{
		stat.Sort(delegate(StructFinal s1, StructFinal s2) { return s1.count.CompareTo(s2.count); });
		
		return stat;
	}
	
	//Mostra resultados na consola
	public void showResultsConsole(List<StructFinal> stat)
	{
		
		Console.WriteLine("\nResultados (Ordenados pela Contagem Crescente): \n");
		stat.ForEach(delegate(StructFinal s) 
		{ 
			Console.WriteLine(String.Format("Ano = 200{0}, Número = {1}", s.year, s.count)); 
		});
		
	}
	
	//Mostra resultados no ficheiro respectivo
	public void showResultsFile(List<StructFinal> stat)
	{
		
		string file = "Estatísticas/statSix.txt";
		TextWriter tw = new StreamWriter(file);
		tw.WriteLine(DateTime.Now);
		tw.WriteLine("Sistema Operativo: " + Environment.OSVersion.ToString());
		tw.WriteLine("");
		tw.WriteLine("Estatística 6 - Número de Docentes que migraram do Estabelecimento " + this.estabelecimento + 
		             " para outro.");
		tw.WriteLine(Environment.NewLine + "(Resultados ordenados pela contagem crescente)");
		tw.Close();
		
		stat.ForEach(delegate(StructFinal s) 
		{
			File.AppendAllText(file, String.Format("Ano = 200{0}, Número = {1}" + 
			                                       Environment.NewLine, s.year, s.count));
		});
		
		Console.WriteLine("\nOs resultados da estatística 6 foram também guardados em ficheiro de texto.");
		Console.WriteLine("Localização: " + file);
		
	}
	
	//Obtém os dados da estatística e retorna-os numa lista de objectos destinados para tal
	public List<StructFinal> getData()
	{
		string connectionString = "URI=file:rebides.db,version=3";
		IDbConnection dbcon;
		dbcon = (IDbConnection) new SqliteConnection(connectionString);
		dbcon.Open();
		IDbCommand dbcmd = dbcon.CreateCommand();
		
		List<StructFinal> stat = new List<StructFinal>();
		
		for(int ano = 0; ano < 10 ; ano++)
		{
			
			if(ano == 0)
			{
				//Quando o ano é 2000, não há dados anteriores para comparar
				//e fazer então a estatística
				stat.Add(new StructFinal(ano, 0));
				continue;
			}
			else
			{
				
				//Verifica primeiro qual os códigos de estabelecimento no ano anterior
				//e actual (ano do ciclo)
				int cod_estabAnt = this.findEstab(ano - 1, this.estabelecimento, dbcon);
				int cod_estabAct = this.findEstab(ano, this.estabelecimento, dbcon);
				
				//Obtem uma lista com os docentes do ano anterior e outra com os do ano actual 
				//(para o estabelecimento pretendido)
				List<StructSix> docAnt = this.findDoc(ano - 1, cod_estabAnt, dbcon);
				List<StructSix> docAct = this.findDoc(ano, cod_estabAct, dbcon);
				
				//Variável que irá conter a contagem final da estatística
				int count = 0;
				
				//Percorre a lista com os docentes do ano anterior
				foreach(StructSix docPrev in docAnt)
				{
					
					//Verifica se no ano actual existe o mesmo docente (objecto) que existia no ano anterior
					StructSix teste = docAct.Find((delegate(StructSix o) { return o.docente == docPrev.docente; }));
					
					//Caso exista, continua-se, o que quer dizer que ele não mudou de estabelecimento
					if(teste != null)
					{
						continue;
					}
					else
					{
						//Caso não exista vai se verificar se ele está actualmente noutro estabelecimento
						bool result = this.fintdDocInEstab(ano, int.Parse(docPrev.docente), dbcon);
						
						//Se o docente está noutro estabelecimento
						//inidica que ele não abandonou apenas o estabelecimento
						//mas migrou para outro, logo entra na contagem
						if(result)
						{
							count++;
								
						}
					}
			
				}
				
				//Guarda os resultados numa lista de objectos StructFinal
				stat.Add(new StructFinal(ano, count));
				
				
			}
			

		}
		
		return stat;
		
	}
	
	//Método que irá obter o codigo de estabelecimento pelo seu nome e ano
	public int findEstab(int ano, string estabelecimento, IDbConnection dbcon)
	{
		
		IDbCommand dbcmd = dbcon.CreateCommand();
		IDataReader reader = null;

		string sqlEstab = String.Format("SELECT DISTINCT id FROM estabelecimento WHERE " + 
				                           "ano = {0} AND designacao LIKE '{1}'", ano, estabelecimento);
			 
		dbcmd.CommandText = sqlEstab;
		reader = dbcmd.ExecuteReader();
				
		string estabelecimento_id = null;
				
		while(reader.Read()) 
		{
			estabelecimento_id = reader.GetString (0);
		}
		
		return int.Parse(estabelecimento_id);
		
	}
	
	//Método que devolve a lista de docentes num determinado ano para um dado estabelecimento
	public List<StructSix> findDoc(int ano, int cod_estab, IDbConnection dbcon)
	{
		
		IDbCommand dbcmd = dbcon.CreateCommand();
		IDataReader reader = null;
		
		List<StructSix> docentes = new List<StructSix>();
		
		string sqlFinal = String.Format("SELECT docente_id FROM registodocencia WHERE " +
					"ano = {0} AND estabelecimento_id = {1}", ano, cod_estab);
				
		dbcmd.CommandText = sqlFinal;
		reader = dbcmd.ExecuteReader();
				
		while(reader.Read()) 
		{
			string docente = reader.GetString (0);
			docentes.Add(new StructSix(docente));
		}
		
		return docentes;
		
	}
	
	//Método que verifica se os docentes estão num estabelecimento
	//Importante para confirmar se os docentes apenas abandoram ou se migraram de estabelecimento
	public bool fintdDocInEstab(int ano, int cod_doc, IDbConnection dbcon)
	{
		
		IDbCommand dbcmd = dbcon.CreateCommand();
		IDataReader reader = null;
		
		string sqlFinal = String.Format("SELECT estabelecimento_id FROM registodocencia WHERE " +
					"ano = {0} AND docente_id = {1}", ano, cod_doc);
				
		dbcmd.CommandText = sqlFinal;
		reader = dbcmd.ExecuteReader();
				
		while(reader.Read()) 
		{
			string estab = reader.GetString (0);
			
			//se se obtem um estabelecimento retorna-se logo true, pois indica 
			//que o docente X está neste ano num estabelecimento
			if(estab != null)
			{
				return true;
			}
			else
			{
				continue;
			}
			
		}
		
		return false;
		
		
	}
	
	
}

//Objecto que servirá controlo à estatística
//Tem como atributos docente e servirá para 
//criar as listas de docentes num estabelecimento e ano
//que posteriormente serão comparadas
public class StructSix
{
	public string docente;
	
	public StructSix(string docente)
	{
		
		this.docente = docente;
		
	}
}

//Objecto que servirá de base à estatística
//Tem como atributos o ano e a contagem final
public class StructFinal
{
	public int year;
	public int count;
	
	public StructFinal(int year, int count)
	{
		this.year = year;
		this.count = count;
	}
}


